// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "LyraCameraMode.h"
#include "Curves/CurveFloat.h"
#include "LyraPenetrationAvoidanceFeeler.h"
#include "DrawDebugHelpers.h"
#include "LyraCameraMode_ThirdPerson.generated.h"

class UCurveVector;

/**
 * ULyraCameraMode_ThirdPerson
 *
 *	一个基础的第三人称相机模式。
 */
UCLASS(Abstract, Blueprintable)
class ULyraCameraMode_ThirdPerson : public ULyraCameraMode
{
	GENERATED_BODY()

public:

	ULyraCameraMode_ThirdPerson();

protected:

	virtual void UpdateView(float DeltaTime) override;

	void UpdateForTarget(float DeltaTime); // 更新目标
	void UpdatePreventPenetration(float DeltaTime); // 更新防止穿透
	void PreventCameraPenetration(class AActor const& ViewTarget, FVector const& SafeLoc, FVector& CameraLoc, float const& DeltaTime, float& DistBlockedPct, bool bSingleRayOnly); // 防止相机穿透

	virtual void DrawDebug(UCanvas* Canvas) const override;

protected:

	// 使用视图俯仰角评估曲线，定义从目标出发的局部空间偏移的曲线。
	UPROPERTY(EditDefaultsOnly, Category = "Third Person", Meta = (EditCondition = "!bUseRuntimeFloatCurves"))
	TObjectPtr<const UCurveVector> TargetOffsetCurve;

	// UE-103986：PIE期间实时编辑RuntimeFloatCurves无法工作（与曲线资源不同）。一旦解决，这将成为默认值，TargetOffsetCurve将被移除。
	UPROPERTY(EditDefaultsOnly, Category = "Third Person")
	bool bUseRuntimeFloatCurves; // 是否使用运行时浮点曲线

	UPROPERTY(EditDefaultsOnly, Category = "Third Person", Meta = (EditCondition = "bUseRuntimeFloatCurves"))
	FRuntimeFloatCurve TargetOffsetX; // 目标偏移X曲线

	UPROPERTY(EditDefaultsOnly, Category = "Third Person", Meta = (EditCondition = "bUseRuntimeFloatCurves"))
	FRuntimeFloatCurve TargetOffsetY; // 目标偏移Y曲线

	UPROPERTY(EditDefaultsOnly, Category = "Third Person", Meta = (EditCondition = "bUseRuntimeFloatCurves"))
	FRuntimeFloatCurve TargetOffsetZ; // 目标偏移Z曲线

	// 改变下蹲偏移混合进入或退出的速度
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Third Person")
	float CrouchOffsetBlendMultiplier = 5.0f; // 下蹲偏移混合乘数

	// 穿透预防
public:
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Collision")
	float PenetrationBlendInTime = 0.1f; // 穿透混合进入时间

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Collision")
	float PenetrationBlendOutTime = 0.15f; // 穿透混合退出时间

	/** 如果为true，执行碰撞检查以防止相机进入世界。 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Collision")
	bool bPreventPenetration = true; // 防止穿透标志

	/** 如果为true，尝试检测附近的墙壁并预先移动相机。有助于防止弹出。 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Collision")
	bool bDoPredictiveAvoidance = true; // 执行预测性避免标志

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collision")
	float CollisionPushOutDistance = 2.f; // 碰撞推出距离

	/** 当相机的距离由于穿透被推入其完整距离的此百分比时 */
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Collision")
	float ReportPenetrationPercent = 0.f; // 报告穿透百分比

	/**
	 * 这些是用于确定相机放置位置的触须射线。
	 * 索引：0：这是我们用于防止碰撞的正常触须。
	 * 索引：1+：如果你设置bDoPredictiveAvoidance=true，这些触须用于扫描潜在的影响，如果玩家朝向该方向旋转并原始地碰撞相机，以便在碰到遮挡物之前拉入相机。
	 */
	UPROPERTY(EditDefaultsOnly, Category = "Collision")
	TArray<FLyraPenetrationAvoidanceFeeler> PenetrationAvoidanceFeelers; // 穿透避免触须数组

	UPROPERTY(Transient)
	float AimLineToDesiredPosBlockedPct; // 瞄准线到期望位置阻塞百分比

	UPROPERTY(Transient)
	TArray<TObjectPtr<const AActor>> DebugActorsHitDuringCameraPenetration; // 相机穿透期间击中的调试Actor数组

#if ENABLE_DRAW_DEBUG
	mutable float LastDrawDebugTime = -MAX_FLT; // 最后绘制调试时间
#endif

protected:
	
	void SetTargetCrouchOffset(FVector NewTargetOffset); // 设置目标下蹲偏移
	void UpdateCrouchOffset(float DeltaTime); // 更新下蹲偏移

	FVector InitialCrouchOffset = FVector::ZeroVector; // 初始下蹲偏移
	FVector TargetCrouchOffset = FVector::ZeroVector; // 目标下蹲偏移
	float CrouchOffsetBlendPct = 1.0f; // 下蹲偏移混合百分比
	FVector CurrentCrouchOffset = FVector::ZeroVector; // 当前下蹲偏移
	
};